package com.weilive.pay.service.apple;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.net.ssl.HttpsURLConnection;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.weilive.core.cache.redis.RedisConfig;
import com.weilive.core.cache.redis.RedisService;
import com.weilive.core.utils.DateUtil;
import com.weilive.core.utils.MD5Utils;
import com.weilive.core.utils.Utils;
import com.weilive.pay.ServerContext;
import com.weilive.pay.dao.mapper.UserCashMapper;
import com.weilive.pay.dao.model.AddEMoney;
import com.weilive.pay.dao.model.CashLog;
import com.weilive.pay.dao.model.CashTx;
import com.weilive.pay.dao.model.UserCash;
import com.weilive.pay.dao.model.UserInfo;
import com.weilive.pay.gate.ApplePayServlet;
import com.weilive.pay.msg.ToPayMsg;
import com.weilive.pay.service.CashTemplate;

@Service
public class ApplePayService {
	private static final Logger logger = LoggerFactory.getLogger(ApplePayServlet.class);
	@Autowired
	private UserCashMapper userCashDao;
	@Autowired
	private CashTemplate cashTemplate;
	@Autowired
	private RedisService redis;

	private static final String APPLE_PAY_URL = "https://buy.itunes.apple.com/verifyReceipt";

	private static final String APPLE_PAY_TEST_URL = "https://sandbox.itunes.apple.com/verifyReceipt";

	/**
	 * 
	 * @param xmlStr
	 * @param url
	 * @return
	 */
	private String checkPay(String xmlStr, String url) {
		HttpsURLConnection urlCon = null;
		try {
			urlCon = (HttpsURLConnection) (new URL(url)).openConnection();
			urlCon.setDoInput(true);
			urlCon.setDoOutput(true);
			urlCon.setRequestMethod("POST");
			urlCon.setRequestProperty("Content-Length", String.valueOf(xmlStr.getBytes().length));
			urlCon.setUseCaches(false);
			urlCon.setConnectTimeout(5 * 1000);
			urlCon.setReadTimeout(60 * 1000);
			// 设置为gbk可以解决服务器接收时读取的数据中文乱码问题
			urlCon.getOutputStream().write(xmlStr.getBytes("UTF-8"));
			urlCon.getOutputStream().flush();
			urlCon.getOutputStream().close();
			StringBuffer readOneLineBuff = new StringBuffer();
			String content = "";
			BufferedReader reader = new BufferedReader(new InputStreamReader(urlCon.getInputStream(), "UTF-8"));
			String line = "";
			while ((line = reader.readLine()) != null) {
				readOneLineBuff.append(line);
			}
			content = readOneLineBuff.toString();
			reader.close();
			return content;
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private String getPayURL() {
		return ServerContext.isWorkingEnv() ? APPLE_PAY_URL : APPLE_PAY_TEST_URL;
	}

	private String getLogKey(String recipe) {
		try {
			return MD5Utils.encryptToHex(recipe);
		} catch (Exception e) {
		}
		return UUID.randomUUID().toString();
	}

	// 没用事物
	public String checkAndSaveLog(long userId, String recipe) {
		try {
			String key = getLogKey(recipe);
			CashLog log = userCashDao.getCashLog(key);
			if (log == null) {
				log = new CashLog();
				log.setId(key);
				log.setRecipe(recipe);
				log.setUser_id(userId);
				log.setStatus(0);
				userCashDao.saveCashLog(log);
			}
			if (log.getStatus() == 1) {
				// 支付成功了
				return "已经到账了";
			}
			if (log.getUser_id() != userId) {
				// 角色不一样
				return "userId不一样";
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return "ok";
	}

	@Transactional
	public String applePay(long userId, String recipe) throws Exception {

		String logKey = getLogKey(recipe);

		JSONObject obj = new JSONObject();
		// String s = Base64Coder.encode(obj.toString());
		obj.put("receipt-data", recipe);

		String result = StringUtils.trim(checkPay(obj.toString(), getPayURL()));

		logger.info("result=" + result);
		if (StringUtils.isBlank(result)) {
			// 充值失败
			return new ToPayMsg("0", "验证错误", null, null).toString();
		}

		JSONObject jsonobj = JSONObject.parseObject(result);

		int status = jsonobj.getIntValue("status");
		// 测试环境去验证
		if (status == 21007) {
			result = StringUtils.trim(checkPay(obj.toString(), APPLE_PAY_TEST_URL));

			logger.info("result=" + result);
			if (StringUtils.isBlank(result)) {
				// 充值失败
				return new ToPayMsg("0", "验证错误", null, null).toString();
			}
			jsonobj = JSONObject.parseObject(result);

			status = jsonobj.getIntValue("status");
		}

		if (status != 0) {
			// 充值失败
			return new ToPayMsg("0", "充值失败", null, null).toString();
		}

		JSONObject jsonobj1 = jsonobj.getJSONObject("receipt");

		int goodsCount = jsonobj1.getIntValue("quantity");
		String goodsId = jsonobj1.getString("product_id");
		String out_trade_no = jsonobj1.getString("transaction_id");

		// int index = product_id.indexOf(".");
		CashTx cashTx = cashTemplate.getCashTx(goodsId);
		double costMoney = 0;// 需要多少钱
		int mibi = 0;// 可得mibi
		int vip = 0;// vip增加天数
		if (cashTx != null) {
			costMoney = cashTx.getCost();
			mibi = cashTx.getCredit();
			if (cashTx.getCreditUnit().toUpperCase().equals("M")) {
				// 是月卡
				vip = cashTx.getCredit();// 增加的月份
			}
		}

		UserCash userCash = userCashDao.getUserCash(out_trade_no);
		if (userCash == null) {
			userCash = new UserCash();
			userCash.setOutTradeNo(out_trade_no);
			userCash.setTradeNo(out_trade_no);
			userCash.setUserId(userId);
			userCash.setGoodsId(goodsId);
			userCash.setGoodsCount(goodsCount + "");
			userCash.setPrice(costMoney);
			userCash.setTotalFee(costMoney);
			userCash.setSellerId("");
			userCash.setSellerEmail("");
			userCash.setBuyerId("");
			userCash.setBuyerEmail("");
			userCash.setPayStatus(1);
			userCash.setExt("Apple-Pay");
			userCash.setCdate(new Date());
			userCashDao.insertSelective(userCash);
			if (vip > 0) {
				// 增加vip日期
				UserInfo userInfo = userCashDao.getUserInfo(userId);
				Date vipDate = userInfo.getVip_expiration();
				if (DateUtil.isExpired(vipDate)) {
					vipDate = new Date();// 过期
				}
				vipDate = DateUtil.addTime(DateUtil.MONTH, vip, vipDate);
				userCashDao.setUserVipDate(userId, vipDate);

				String userKey = RedisConfig.USER_INFO_PREF + userId;
				if (redis.exists(userKey)) {
					Map<String, String> setMap = new HashMap<String, String>();
					setMap.put(RedisConfig.USER_VIP_EXPIRATION, Utils.parseString((vipDate.getTime() / 1000L), "0"));
					setMap.put(RedisConfig.USER_UPDATED_TIME, DateUtil.dateFormat(new Date()));
					redis.hmset(userKey, setMap);
				}
			} else {
				// 加钱操作
				AddEMoney res = userCashDao.addEMoney(userId, (long) mibi, userCash.getTradeId());
				logger.info("userId={},用户可得mibi={}, out_trade_no={}", new Object[] { userId, mibi, out_trade_no });
				if (res.getIs_success_flag().equals("N")) {
					throw new RuntimeException(res.getErr_msg());
				}
			}
			// 修改成功到账
			userCashDao.useCashSuccess(logKey);
		}
		UserInfo userInfo = userCashDao.getUserInfo(userId);
		return new ToPayMsg("1", null, userInfo.getE_money(), userInfo.getVip_expiration()).toString();
	}
}
